<template>
  <div
    class="noteContentViewer customScrollbar"
    ref="noteContentViewer"
    :style="{
      left: left + 'px',
      top: top + 'px',
      visibility: show ? 'visible' : 'hidden'
    }"
    @click.stop
    @mousedown.stop
    @mousemove.stop
    @mouseup.stop
    @wheel.stop
  >
    <div class="noteContentWrap customScrollbar" ref="noteContentWrap"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, defineProps } from 'vue'
import { useEventBus } from '@/hooks'
import Viewer from '@toast-ui/editor/dist/toastui-editor-viewer'
import '@toast-ui/editor/dist/toastui-editor-viewer.css'

const props = defineProps({
  mindMap: {
    type: Object,
    default() {
      return null
    }
  }
})

const { $on, $off, $emit, $once } = useEventBus()

const noteContentViewer = ref(null)
const noteContentWrap = ref(null)
const editor = ref(null)
const show = ref(false)
const left = ref(0)
const top = ref(0)
const node = ref(null)

const onNodeActive = (...args) => {
  const nodes = [...args[1]]
  if (nodes.length > 0) {
    if (nodes[0] !== node.value) {
      hideNoteContent()
    }
  } else {
    hideNoteContent()
  }
}

// 显示备注浮层
const onShowNoteContent = (content, leftPos, topPos, nodeData) => {
  node.value = nodeData
  editor.value.setMarkdown(content)
  handleALink()
  updateNoteContentPosition(leftPos, topPos)
  show.value = true
}

// 超链接新窗口打开
const handleALink = () => {
  const list = noteContentViewer.value.querySelectorAll('a')
  Array.from(list).forEach(a => {
    a.setAttribute('target', '_blank')
  })
}

// 更新位置
const updateNoteContentPosition = (leftPos, topPos) => {
  const { width, height } = noteContentViewer.value.getBoundingClientRect()
  const { right, bottom } = props.mindMap.elRect
  left.value = leftPos + width > right ? right - width : leftPos
  top.value = topPos + height > bottom ? bottom - height : topPos
}

// 画布缩放事件
const onScale = () => {
  if (!node.value || !show.value) return
  const { left: leftPos, top: topPos } = node.value.getNoteContentPosition()
  updateNoteContentPosition(leftPos, topPos)
}

// 隐藏备注浮层
const hideNoteContent = () => {
  show.value = false
}

// 初始化编辑器
const initEditor = () => {
  if (!editor.value) {
    editor.value = new Viewer({
      el: noteContentWrap.value
    })
  }
}

onMounted(() => {
  $on('showNoteContent', onShowNoteContent)
  $on('hideNoteContent', hideNoteContent)
  document.body.addEventListener('click', hideNoteContent)
  $on('node_active', onNodeActive)
  $on('scale', onScale)
  $on('translate', onScale)
  $on('svg_mousedown', hideNoteContent)
  $on('expand_btn_click', hideNoteContent)
  
  props.mindMap.el.appendChild(noteContentViewer.value)
  initEditor()
})

onBeforeUnmount(() => {
  $off('showNoteContent', onShowNoteContent)
  $off('hideNoteContent', hideNoteContent)
  document.body.removeEventListener('click', hideNoteContent)
  $off('node_active', onNodeActive)
  $off('scale', onScale)
  $off('translate', onScale)
  $off('svg_mousedown', hideNoteContent)
  $off('expand_btn_click', hideNoteContent)
})
</script>

<style lang="less" scoped>
.noteContentViewer {
  position: fixed;
  background-color: #fff;
  padding: 10px;
  border-radius: 5px;
  box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.06);
  z-index: 2;

  .noteContentWrap {
    max-width: 250px;
    max-height: 300px;
    overflow-y: auto;
  }
}
</style>
